#include "server.h"

using namespace easyWebServer;



Server::Server(const string & ip, const uint16_t port)
{
    Singleton<ThreadPool>::getInstance().setThreadNum(Singleton<yazi::json::Json>::getInstance()["threadPoolNumber"].asInt());
    Singleton<ThreadPool>::getInstance().start();

    sigset_t sigsets;
    sigemptyset(&sigsets);
    sigaddset(&sigsets, SIGINT);
    sigprocmask(SIG_BLOCK, &sigsets, NULL);
    m_signalfd = signalfd(-1, &sigsets, 0);

    SOCKETINSTANCE.setAddr(ip, port);
    SOCKETINSTANCE.createSocketfd();
    SOCKETINSTANCE.setPortReuse();
    SOCKETINSTANCE.bindAddr();
    SOCKETINSTANCE.listenPort();
    SOCKETINSTANCE.setNoBlock(SOCKETINSTANCE.getfd(), true);

    EPOLLINSTANCE.setEpollEventSize(1024);
    EPOLLINSTANCE.createEpollfd();
    EPOLLINSTANCE.addEvent(SOCKETINSTANCE.getfd(), EPOLLIN);
    EPOLLINSTANCE.addEvent(m_signalfd, EPOLLIN | EPOLLOUT);
    
    Singleton<TSList>::getInstance().clear();

}

Server::~Server()
{
    info("server quit\n");
    Singleton<ThreadPool>::getInstance().stop();
}

void Server::initServer()
{

}

void Server::start()
{
    while(m_isStop == false)
    {
        int n = EPOLLINSTANCE.epollWait(1000);
        for(int i = 0; i < n; i++)
        {
            if(EPOLLINSTANCE.getEventList()[i].data.fd == m_signalfd)
            {
                m_isStop = true;
            }
            if(EPOLLINSTANCE.getEventList()[i].data.fd == SOCKETINSTANCE.getfd())
            {
                int fd = SOCKETINSTANCE.acceptClient();
                debug("new Connect fd = %d", fd);
                SOCKETINSTANCE.setNoBlock(fd, true);
                unique_ptr<Task> task(new Task(fd));
                EPOLLINSTANCE.addEvent(fd, EPOLLIN, task);
            }
            else if (EPOLLINSTANCE.getEventList()[i].events & EPOLLIN)
            {
                unique_ptr<Task> task((Task*)EPOLLINSTANCE.getEventList()[i].data.ptr);
                int fd = task->getFd();
                debug("epollEventIn fd = %d", fd);
                Singleton<Dispatcher>::getInstance().addTask(task);
            }
            else if(EPOLLINSTANCE.getEventList()[i].events & EPOLLOUT)
            {
                unique_ptr<Task> task((Task*)EPOLLINSTANCE.getEventList()[i].data.ptr);
                int fd = task->getFd();
                debug("epollEventOut fd = %d", fd);
                Singleton<Dispatcher>::getInstance().addTask(task);
            }
        }
    }
}



